import { DataLink, LinkModel } from '@grafana/data';
import { t } from '@grafana/i18n';
import {
  SceneComponentProps,
  sceneGraph,
  SceneObjectBase,
  SceneObjectState,
  VariableDependencyConfig,
  VizPanel,
} from '@grafana/scenes';
import { Dropdown, Icon, Menu, PanelChrome, ToolbarButton } from '@grafana/ui';

import { getPanelLinks } from './PanelMenuBehavior';
import { locationService } from '@grafana/runtime';

interface VizPanelLinksState extends SceneObjectState {
  rawLinks?: DataLink[];
  links?: LinkModel[];
  menu: VizPanelLinksMenu;
}

export class VizPanelLinks extends SceneObjectBase<VizPanelLinksState> {
  protected _variableDependency = new VariableDependencyConfig(this, {
    onAnyVariableChanged: () => {
      if (this.state.rawLinks && this.state.rawLinks.length > 0) {
        this.forceRender();
      }
    },
  });

  static Component = VizPanelLinksRenderer;
}

function VizPanelLinksRenderer({ model }: SceneComponentProps<VizPanelLinks>) {
  const { menu, rawLinks } = model.useState();
  sceneGraph.getTimeRange(model).useState();

  if (!(model.parent instanceof VizPanel)) {
    throw new Error('VizPanelLinks must be a child of VizPanel');
  }

  if (!rawLinks || rawLinks.length === 0) {
    return null;
  }

  if (rawLinks.length === 1) {
    const link = getPanelLinks(model.parent)[0];

    const TARGET_PARAMS = ['mView', 'mViewWidth', 'mViewHeight', 'mViewType', 'noParams', 'mViewTitle'];
    const linkClick = (e: any) => {
      e.preventDefault();
      let urlObj = new URL(link.href);
      let currentUrl = new URL(window.location.href);

      const allParamKeys = Array.from(urlObj.searchParams.keys());

      const paramsToDelete = allParamKeys.filter(
        (key) => !TARGET_PARAMS.includes(key)
      );

      paramsToDelete.forEach((key) => {
        urlObj.searchParams.delete(key);
      });

      urlObj.searchParams.forEach((value, key) => {
        currentUrl.searchParams.set(key, value);
      })

      locationService.replace({search: currentUrl.searchParams.toString()})
    }

    return (
      <PanelChrome.TitleItem href={link.href} onClick={linkClick} target={link.target} title={link.title}>
        <Icon name="external-link-alt" size="md" />
      </PanelChrome.TitleItem>
    );
  }

  return (
    <Dropdown
      overlay={() => {
        return <menu.Component model={menu} key={menu.state.key} />;
      }}
    >
      <ToolbarButton
        icon="external-link-alt"
        iconSize="md"
        aria-label={t('dashboard-scene.viz-panel-links-renderer.aria-label-panel-links', 'Panel links')}
      />
    </Dropdown>
  );
}

export class VizPanelLinksMenu extends SceneObjectBase<Omit<VizPanelLinksState, 'menu' | 'rawLinks'>> {
  static Component = VizPanelLinksMenuRenderer;
}

function VizPanelLinksMenuRenderer({ model }: SceneComponentProps<VizPanelLinks>) {
  const { links } = model.useState();

  if (!links) {
    return null;
  }

  return (
    <Menu>
      {links?.map((link, idx) => {
        return <Menu.Item key={idx} label={link.title} url={link.href} target={link.target} onClick={link.onClick} />;
      })}
    </Menu>
  );
}
